package com.stone.framework.basic.dict.service.impl;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.stone.framework.basic.dict.entity.DictMember;
import com.stone.framework.basic.dict.repository.DictMemberRepository;
import com.stone.framework.basic.dict.service.DictMemberService;
import com.stone.framework.core.cache.BasicConstant;
import com.stone.framework.core.exception.BusinessException;
import com.stone.framework.core.util.Beans;
import com.stone.framework.message.basic.dict.DictMemberPageResBody;
import com.stone.framework.message.basic.dict.DictMemberReqBody;
import com.stone.framework.message.basic.dict.DictMemberResBody;

@Service
@Transactional(readOnly = true)
public class DictMemberServiceImpl implements DictMemberService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DictMemberServiceImpl.class);

    @Autowired
    private DictMemberRepository dictMemberRepository;

    @Override
    public Page<DictMemberPageResBody> queryPage(String categoryCode, Pageable pageable) {
        return dictMemberRepository.findByDictCategoryCode(categoryCode, pageable).map(entity -> {
            DictMemberPageResBody resBody = new DictMemberPageResBody();
            Beans.copyProperties(entity, resBody);
            return resBody;
        });
    }

    @Override
    @Cacheable(value = BasicConstant.PREFIX_DICT, key = "#code")
    public List<DictMemberResBody> queryByCategoryCode(String code) {
        List<DictMember> list = dictMemberRepository.findByDictCategoryCode(code);
        if (list.isEmpty()) { // 抛出异常使cache失效
            throw new BusinessException("[%s] 不存在", code);
        }
        return list.stream().filter(entity -> !entity.disabled())
            .sorted((o1, o2) -> o1.getOrder().compareTo(o2.getOrder())).map(entity -> {
                DictMemberResBody resBody = new DictMemberResBody();
                Beans.copyProperties(entity, resBody);
                return resBody;
            }).collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = BasicConstant.PREFIX_DICT_KV, key = "#code")
    public Map<String, String> queryKVByCategoryCode(String code) {
        List<DictMember> list = dictMemberRepository.findByDictCategoryCode(code);
        if (list.isEmpty()) {
            throw new BusinessException("[%s] 不存在", code);
        }
        return list.stream().filter(entity -> !entity.disabled())
            .sorted((o1, o2) -> o1.getOrder().compareTo(o2.getOrder()))
            .collect(Collectors.toMap(DictMember::getCode, DictMember::getName, (k, v) -> k));
    }

    @Override
    @Transactional(readOnly = false)
    @CacheEvict(value = {BasicConstant.PREFIX_DICT, BasicConstant.PREFIX_DICT_KV},
        key = "#list.get(0).getDictCategoryCode()")
    public void save(List<DictMemberReqBody> list) {
        List<DictMemberReqBody> addList = list.stream().filter(reqBody -> reqBody.isAdd()).collect(Collectors.toList());
        List<DictMemberReqBody> updateList =
            list.stream().filter(reqBody -> reqBody.isUpdate()).collect(Collectors.toList());
        List<DictMemberReqBody> deleteList =
            list.stream().filter(reqBody -> reqBody.isDelete()).collect(Collectors.toList());

        this.add(addList);
        this.update(updateList);
        this.delete(deleteList);
    }

    private void add(List<DictMemberReqBody> list) {
        List<DictMember> entities = list.stream().map(reqBody -> {
            DictMember entity = new DictMember();
            Beans.copyProperties(reqBody, entity);
            return entity;
        }).collect(Collectors.toList());
        dictMemberRepository.saveAll(entities);
    }

    private void update(List<DictMemberReqBody> list) {
        List<Long> idList = list.stream().map(DictMemberReqBody::getId).collect(Collectors.toList());
        List<DictMember> entities = dictMemberRepository.findAllById(idList);
        entities.forEach(entity -> {
            list.stream().filter(reqBody -> reqBody.getId().equals(entity.getId())).findAny()
                .ifPresent(reqBody -> Beans.copyProperties(reqBody, entity));
        });
        dictMemberRepository.saveAll(entities);
    }

    private void delete(List<DictMemberReqBody> list) {
        List<Long> idList = list.stream().map(DictMemberReqBody::getId).collect(Collectors.toList());
        List<DictMember> entities = dictMemberRepository.findAllById(idList);
        dictMemberRepository.deleteInBatch(entities);
    }

}
